package gui.menu.addons;

import java.awt.AlphaComposite;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.util.ArrayList;

import tiles.IsometricSprite;

import gui.addon.Drawable;

public abstract class ToolMenuItemPickerItem {

	private final Color BG_COLOR = new Color(51, 51, 51, 200);
	private final Color HIGHLIGHT_COLOR = new Color(255, 165, 0, 200);
	protected final int OPTIONS_WIDTH = 80;
	protected final int OPTIONS_HEIGHT = 80;
	protected final int BORDER_SIZE = 1;
	protected final int TITLE_HEIGHT = 20;

	protected int x, y;
	protected Rectangle rect;
	protected IsometricSprite tile;
	protected boolean highlighted = false;
	protected boolean preRender = false;

	protected BufferedImage img_icon = null;
	protected BufferedImage display_img = null;

	protected ArrayList<BufferedImage> images;

	public ToolMenuItemPickerItem(BufferedImage img) {
		this.img_icon = img;
	}

	public void setPoint(Point p) {
		this.x = p.x;
		this.y = p.y;
	}

	private void drawBorder(Graphics g, int main_x, int main_y) {
		rect = new Rectangle(main_x + x * OPTIONS_WIDTH, main_y + y
				* OPTIONS_HEIGHT, OPTIONS_WIDTH, OPTIONS_HEIGHT);

		g.setColor((highlighted ? HIGHLIGHT_COLOR : BG_COLOR));
		g.fillRect(rect.x, rect.y, rect.width, rect.height);
		g.setColor(Color.black);
		g.drawRect(rect.x, rect.y, rect.width, rect.height);
	}

	private void drawImage(Graphics g, int main_x, int main_y) {
		if (img_icon == null)
			return;
		g.drawImage(img_icon, main_x, main_y, OPTIONS_WIDTH, OPTIONS_HEIGHT,
				null);

	}

	public boolean contains(Point p) {
		return rect.contains(p);
	}

	public void mouseAction(MouseEvent e) {
		switch (e.getID()) {
		case 503:
			highlight(e.getSource());
			break;

		case 500:
			preRender = !preRender;
			preRender();
			break;

		default:
			break;
		}
	}

	private void preRender() {
		if (display_img == null)
			return;
		
		if (!preRender && !willCollide()) {
			addItem(display_img);
		}
	}

	public void mouseScrolled(MouseWheelEvent e) {
		if (!preRender || images.size() <= 1)
			return;

		int nr = images.indexOf(display_img);
		int next = nr + e.getWheelRotation();
		setDisplayImg(images.get(next >= images.size() ? 0 : next < 0 ? images
				.size() - 1 : next));
	}

	public void setHighlight(boolean b) {
		highlighted = b;
	}

	public abstract void addItem(BufferedImage display_img);

	private void highlight(Object src) {
		if (src instanceof Canvas) {
			((Canvas) src).setCursor(Cursor
					.getPredefinedCursor(Cursor.HAND_CURSOR));
		}
		setHighlight(true);
	}

	public void setIsometricPoint(IsometricSprite iso) {
		this.tile = iso;
	}

	private void drawPreRender(Graphics g) {
		if (!preRender || display_img == null)
			return;
		
		BufferedImage tmp_img = cloneImage(display_img);
		
		if (willCollide()) {
			tmp_img = makeRed(tmp_img);
		}
		if (g instanceof Graphics2D) {
			AlphaComposite ac = AlphaComposite.getInstance(
					AlphaComposite.SRC_OVER, 0.8f);
			((Graphics2D) g).setComposite(ac);
		}
		Point tmp = tile.getRelativeImageLocation(tmp_img.getWidth(), tmp_img
				.getHeight());
		g.drawImage(tmp_img, tmp.x, tmp.y, null);
	}

	public void draw(Graphics g, int x, int y) {
		drawBorder(g, x, y);
		drawImage(g, x, y);
		drawPreRender(g);
	}

	private void setDisplayImg(BufferedImage img) {
		display_img = img;
		
	}
	
	protected void addImage(BufferedImage img) {
		if (images == null) {
			images = new ArrayList<BufferedImage>();
			setDisplayImg(img);
		}
		images.add(img);
	}

	public void mainMenuClosed() {
		preRender = false;
	}

	private boolean willCollide() {
		if (!tile.isBuildable())
			return true;
		Point drawPoint = tile.getRelativeImageLocation(display_img.getWidth(),
				display_img.getHeight());
		// Rectangle tmp = new Rectangle(drawPoint.x, drawPoint.y,
		// display_img.getWidth(), display_img.getHeight());
		Rectangle tmp = display_img.getData().getBounds();
		tmp.translate(drawPoint.x, drawPoint.y);
		return collideLoop(tile.getLinkedPoints(), tmp,
				new ArrayList<IsometricSprite>());
	}

	private boolean collideLoop(ArrayList<IsometricSprite> spriteList,
			Rectangle r, ArrayList<IsometricSprite> isos) {
		for (IsometricSprite sp : spriteList) {
			if (!isos.contains(sp) && sp.getRelativeCollide(r) && sp != tile) {
				if (!sp.isBuildable())
					return true;
				isos.add(sp);
				collideLoop(sp.getLinkedPoints(), r, isos);
			}
		}
		return false;
	}

	private BufferedImage cloneImage(BufferedImage bi) {
		ColorModel cm = bi.getColorModel();
		boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
		WritableRaster raster = bi.copyData(null);
		return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
	}

	private BufferedImage makeRed(BufferedImage bi) {
		for (int i = 0; i < bi.getHeight(); i++) {
			for (int j = 0; j < bi.getWidth(); j++) {
				int rgb = bi.getRGB(j, i);

				// System.out.println(rgb);
				if (rgb != 0)
					bi.setRGB(j, i, 0xFF330000);// Set the color to black (0);

			}
		}
		return bi;
	}
}
